package com.tanlu.tcc;

import com.tanlu.tcc.annotation.Propagation;
import com.tanlu.tcc.annotation.TransactionStatus;
import com.tanlu.tcc.domain.Command;
import com.tanlu.tcc.domain.Participant;
import com.tanlu.tcc.domain.Transaction;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TransactionContext {

    @Autowired
    private AmqpTemplate rabbitmqTemplate;

    public String serviceName;

    public void send(Command command){
        System.out.println("ttc Sender:" +command.getTransactionStatus());
        this.rabbitmqTemplate.convertAndSend("transaction", command);
    }

    public void registerService(String serviceName) {
        this.serviceName = serviceName;
    }


    public void commit(Transaction transaction) {
        try {
            for(Participant participant : transaction.getParticipants()) {

                    if (participant.getServiceName().equals(serviceName)) {
                        participant.commit();
                    }
            }
        } catch (Exception e) {
            e.printStackTrace();
            rollback(transaction);
        } finally {
            end(transaction);
        }
    }

    public void rollback(Transaction transaction) {
        try {
            for(Participant participant : transaction.getParticipants()) {
                if(participant.getServiceName().equals(serviceName)) {
                    participant.rollback();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void transactionTry(Participant participant, Propagation propagation, int outTime) {
        Command tryCommand = new Command();
        tryCommand.setOuttime(outTime);
        tryCommand.setPropagation(propagation);
        tryCommand.setTransactionStatus(TransactionStatus.Try);
        tryCommand.setObject(participant);
        System.out.println("transactionTry");
        send(tryCommand);
    }

    public void confirm() {
        Command confirmCommand = new Command();
        confirmCommand.setTransactionStatus(TransactionStatus.Confirm);
        send(confirmCommand);
    }


    public void end(Transaction transaction) {
        //发送结束消息
        Command endCommand = new Command();
        endCommand.setTransactionStatus(TransactionStatus.End);
        endCommand.setObject(transaction);
        send(endCommand);
    }

    public void cancel() {
        //发送退出消息
        Command cancelCommand = new Command();
        cancelCommand.setTransactionStatus(TransactionStatus.Cancel);
        send(cancelCommand);
    }


    public void handler(Command command) {
        System.out.println("ttc receiver:"+command.getTransactionStatus());
        if(command.getTransactionStatus() == TransactionStatus.Confirm) {
            commit((Transaction)command.getObject());
        } else if(command.getTransactionStatus() == TransactionStatus.Cancel) {
            rollback((Transaction)command.getObject());
        }
    }

}
